; Grange Murder standard adventure routines. 
;
 begin
cif debugmode
code -
 prs "*****AASTAND*****"
code +
cend
;
; Print text info for current ROOM
.PrintRoom
 code -
 message cr
 code +
 gosub @SpecialActor ; Sam was...
 m1=ShortRoomDescs
 add m1,room
 gosub @printm1dot
 searchpos=room
 hisearchpos=0
 return ; don't print objects GMJ 12/9/89
;---
.printOBJECTS
; GO THROUGH CURRENT OBJECT POSITION LIST,
; AND DISPLAY ALL THE OBJECTS AT (HISEARCHPOS,SEARCHPOS)
 OWTYPE=OWOBJECTS
 GOSUB @INITGETOBJ
 TOTALObjectsPrinted=0
 wordsoutput=1
 printingobjects=true
; numobjectfound=0
 CurrentObjectsPrinted=0
 LastCurrentpos=0
 lastHicurrentpos=0
.PO1
 GOSUB @GETNEXTOBJECT
 IF OBJECT>MAXOBJECTVISIBLE THEN PO1
 IF OBJECT=0 THEN @POEND
 if searchpos=0 then @poend
 GOSUB @CHECKIFOBVIOUS
 IF OBVIOUS=FALSE THEN @PO3
 if object=user then @po3
 x1=hicurrentpos(user)
 if x1=0 then po1notInContainer
; don't describe container of user...
 x1=currentpos(user)
 if x1=object then @po3
.po1NotInContainer
;
 x1=hicurrentpos(object)
 x2=currentpos(object)
 if x1<>LastHicurrentpos then popc
 if x2=lastcurrentpos then po2
.popc
; don't print containment until either two contents are found,
; or we know only a single container is present.
 if CurrentObjectsPrinted<>1 then popc1
 gosub @DelayedPrintContainment
.popc1
 LastHicurrentpos=x1
 LastCurrentpos=x2
 CurrentObjectsPrinted=0
 GOSUB @OUTWORDNONE ; output any buffered words
 SaveHiSearchpos=hisearchpos
 SaveSearchpos=searchpos
.PO2
 add TotalObjectsPrinted,c1
 add currentObjectsPrinted,c1
 if currentObjectsPrinted<>2 then po2a
; multiple objects with same containment type...
 pluralOffset=30
 GOSUB @PRINTCONTAINMENT ; PRINT CONTAINER ON FIRST OBJECT FOUND ONLY
 pluralOffset=0
 ;
.po2a
 WORD1=OBJECT
 WORD2=0
 GOSUB @OUTWORD12 ; Output object name (delayed effect)
.PO3
 goto @po1
;
.poend
 if currentObjectsPrinted<>1 then poend1
; have got to end of list, and haven't printed last
; object because we didn't know if it would be the only
; object with its containment type
 gosub @DelayedPrintContainment
.poend1
 printingobjects=false
 gosub @outwordnone ; output any buffered words
 if wanttoprintand=false then @poret
 goto @printDOT
;---
.CHECKIFOBVIOUS
; see if 'OBJECT' is immediately obvious
 OBVIOUS=TRUE
 IF SEARCHDEPTH=0 THEN CIORET
 X1=HICURRENTPOS(OBJECT)
 IF X1=0 THEN CIORET ; things on ground are always obvious
 X1=CURRENTPOS(OBJECT)
 if printingobjects=true then cionotactor
 if x1=actor then cioret ; actor's possesions are always obvious
.cionotactor
 ADD X1,X1
; look at hi initial position of container
 X2=OBJECTSTART(X1)
 IF X2>127 THEN CIORET ; 'obvious' bit set
 OBVIOUS=FALSE
.CIORET
 RETURN
;---
.GETNEXTOBJECT
; RETURN OBJECT=OBJECT FOUND
;    SEARCHPOS=ROOM OR CONTAINER WHERE FOUND
;  HISEARCHPOS=TYPE OF CONTAINMENT (=0 FOR ROOMS)
;
; BEFORE FIRST CALL, GOSUB INITGETOBJ AND SETUP HI,SEARCHPOS
; AT END OF SEARCH, ALL ZEROS ARE RETURNED
;
 X1=MAXOBJECTVISIBLE
code -
 GETNEXT X1 HISEARCHPOS SEARCHPOS OBJECT x2 SEARCHDEPTH
code +
.poret
 RETURN
;---      
.INITGETOBJ
 SEARCHDEPTH=1
 X1=0
code -
 GETNEXT X1 X1 X1 X1 X1 X1
code +
 RETURN
;---
.delayedPrintContainment
; save (hi)searchpos, restore old hi(searchpos) for object printed,
; and print it!
 x1=searchpos
 x2=hisearchpos
 searchpos=savesearchpos
 hisearchpos=savehisearchpos
 savesearchpos=x1
 savehisearchpos=x2
 objectsave=object
 gosub @PrintContainment ; only a single object in the last position
 searchpos=savesearchpos
 hisearchpos=savehisearchpos
 object=objectsave
 x1=hicurrentpos(object)
 x2=currentpos(object)
 return
;---
;.printOBJECTS
; gosub @OUTWORDNONE ; flush any buffered words
; OWTYPE=OWOBJECTS
; Object=2
; TotalObjectsPrinted=0
;.po1
; pos=searchpos
; hipos=hisearchpos
; gosub @checkobjectpos
; if result=false then ponext
; if totalobjectsprinted<>0 then po2
; gosub @PrintContainment
;.po2
; WORD1=OBJECT
; WORD2=0
; GOSUB @OUTWORD12 ; Output object name (delayed effect)
; add totalobjectsprinted,c1
;.ponext
; add Object,c1
; if Object>MaxObjectVisible then @OutWordNone
; goto @po1
;---
.printCONTAINMENT
 if searchpos=0 then pcret
 wanttoprintand=false
 X5=1600 ; BASE FOR CONTAINMENT MESSAGES (You can see)
 IF SEARCHPOS<>ACTOR THEN PC1
 X5=1700 ; BASE for 'You are wearing' and 'You are carrying'
.PC1
 ADD X5,HISEARCHPOS ; first half of containment message
code -
 MESSAGE X5
code +
 IF HISEARCHPOS=0 THEN PCRET ; DON'T PRINT 'THE object' FOR 'YOU CAN SEE'
 X1=SEARCHPOS ; CONTAINER OBJECT NUMBER
 GOSUB @printTHEobjectx1
 X1=40
 ADD X5,X1 ; second half of containment message
 add x5,pluralOffset
code -
 MESSAGE X5
code +
.PCRET
 RETURN
;---
.printleaving
 if room<>currentuserroom then plret
 if executingracetrack<>false then plret
 m1=cr
 gosub @printm1
 gosub @printactor
code -
 message 2824
code +
.plret
 return
;---
.printarrival
 if room<>currentuserroom then plret
 if executingracetrack<>false then plret
 m1=cr
 gosub @printm1
 gosub @printactor
code -
 message 2825
code +
 return
;---
.checkifaccessible
; return RESULT=TRUE if OBJECT is accessible to VERB
; objects must be present in way HISEARCHPOS
 result=179 ; dummy value
 gosub @specialcheckifaccessible
 if result<>179 then ciaret ; changed by routine, so accept verdict
;
.CIANOTOMNI
 IF HISEARCHPOS<>NONSPECIFIC THEN CIANOTNS
 POS=ROOM
 HIPOS=0
 GOSUB @CHECKOBJECTPOS
 IF RESULT=FALSE THEN CIAISITOWNED
; object can be either owned or on the ground. if on the ground, then 
; approach it...
 POS=actor
 HIPOS=NONSPECIFIC
 GOSUB @CHECKOBJECTPOS ; looking on ground only. if carried, can't be
 IF RESULT=true then ciaret
 result=true
 goto @AACheckIfAccessible
.CIAHAVECHECKED
.ciaret
 return
;
.CIANOTNS
 IF HISEARCHPOS<>NOUNCARRIED THEN CIANOTCARRIED
.CIAISITOWNED
 POS=actor
 HIPOS=NONSPECIFIC
 GOSUB @CHECKOBJECTPOS
 GOTO CIAHAVECHECKED
;
.CIANOTCARRIED
 POS=actor
 HIPOS=NONSPECIFIC
 GOSUB @CHECKOBJECTPOS ; looking on ground only. if carried, can't be
 IF RESULT=TRUE THEN @RETURNFALSE ; CIAHAVECHECKED
 POS=ROOM
 HIPOS=0
 gosub @CHECKOBJECTPOS
 goto @AACheckIfAccessible ; reached hires position?
;---
.SELECTOBJECTPOS
; given VERB,PREP
; set up HISEARCHPOS to show where the objects which follow on
; the input line must be - i.e.
; NOUNONGROUND, NOUNCARRIED or NONSPECIFIC
 HISEARCHPOS=NOUNONGROUND
 IF VERB=ITAKE THEN SOPRET
 IF VERB=ISTAND THEN SOPRET
 HISEARCHPOS=NOUNCARRIED
 IF VERB=IDROP THEN SOPRET
 IF VERB=IGIVE THEN SOPRET
 HISEARCHPOS=NONSPECIFIC
.SOPRET
 RETURN
;---
.CHECKOBJECTPOS
; return RESULT=TRUE if 'OBJECT' is
; at 'HIPOS','POS'
; if POS=0, it is treate as NONSPECIFIC
; likewise, HIPOS=NONSPECIFIC is handled
; return X4=lo position of object (or object if on ground)
 if object>MaxObject then CopNotFound ; failsafeCode
 X4=OBJECT
.COP1
 IF POS=0 THEN COPHI
 X1=CURRENTPOS(X4)
 if x1=0 then copnotfound
 IF X1<>POS THEN COPNOTYET
.COPHI
; lo address is same, now check hi address
 X1=HICURRENTPOS(X4)
 IF X1=0 THEN COPHI1
 IF HIPOS=NONSPECIFIC THEN COPFOUND ; provided object is contained
.COPHI1
 IF X1<>HIPOS THEN COPNOTYET
.COPFOUND
 goto @ReturnTrue
;
.COPNOTFOUND
 goto @ReturnFalse
;
.COPNOTYET
 X1=HICURRENTPOS(X4)
 IF X1=0 THEN COPNOTFOUND
 X4=CURRENTPOS(X4)
 GOTO @COP1
;---
.checkifpresent
; Return result=TRUE if OBJECT is in ROOM
 gosub getobjectposx2
 result=FALSE
 if x2<>room then cipret
 result=TRUE
.cipret
 return
;---
.getobjectposx2
 x2=0
 if object>MaxObject then @ReturnFalse
 x4=object
.gopx4
; Return 'x2'=current pos of object X4
;
; Set up room as actor's room if object is of the omni-type
 if x4<MinRoomObject then GOPNotRoomObject
 if x4>MaxRoomObject then GOPNotRoomObject
 x2=room
 return
.GOPNotRoomObject
;
 x2=CURRENTPOS(X4)
 if x2=0 then gopfound ; not found really
 X1=HICURRENTPOS(X4)
 IF X1=0 THEN gopfound
 X4=x2
 GOTO gopx4
.gopfound
 result=FALSE
 if x2<>room then gopret
 result=TRUE
.gopret
 RETURN
;---
.ReturnTrue
 result=true
 return
;---
.ReturnFalse
 result=false
 return
;---
; RANDOM NUMBER AND MATHS ROUTINES..
;
.randomx1modx2 ; return random x1.. 0<=x1<=x2
code -
 random x1
code +
;
.x1modx2 ; return remainder of division
 if x2=0 then dividebyzero
.mod1
 if x1<x2 then x1modx2ret
 sub x1,x2
 goto mod1
;---
;.x1divx2 ; return x1=answer of division without remainder
;; and x2+x3=remainder
; x3=x2
; x2=x1
; if x3=0 then dividebyzero
; x1=0 ; will be answer
;.x1divx2a
; sub x2,x3
; if x2>negative then x1divret
; add x1,c1
; goto x1divx2a
.x1divret
.dividebyzero
.x1modx2ret
 return
;---
.VALUETIMES256
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 ADD VALUE,VALUE
 RETURN
;---